转载自掘金网络,原文链接:https://juejin.im/post/5c99cbdee51d455b251df9eb
1 环境搭建、创建、运行
1.1 介绍
egg.js是阿里旗下基于node.js和koa是一个node企业级应用开发框架,可以帮助开发团队,和开发人员减少成本。
基于koa2、es6、es7使得node具有更有规范的开发模式,更低的学习成本、更优雅的代码、更少的维护成本。
1.2 环境搭建
1、要求nodejs版本必须大于8.0并且要用LTS 版本
2、创建egg的环境 npm i egg-init -g / cnpm i egg-init -g (只需要安装一次)
3、创建项目
cd 到目录里面 (注意目录不要用中文 不要有空格)
1.3 创建
1 | $ npm i egg-init -g |
1.4 运行项目
1 | npm run dev |
2 目录结构介绍
2.1 目录结构
1 | egg-project |
3 访问路由
egg在设计完全符合比较好的mvc的设计模式。
3.1 那么什么是mvc呢?
全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范。
在egg中视图 (view)、控制器(controller) 和数据模型 Model(Service) 和配置文件(config)
3.2 控制器(controller)
app/controller
目录下面实现 Controller
1 | // app/controller/home.js |
输入 npm run dev 查看 http://127.0.0.1:7001 输出 hi, world
我认为控制器就是一个接口,他管理输入和输出
*同样你可以在app/controller 目录下 写很多个这样个js的,来代表接口
3.3 路由(Router)
主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系, 框架约定了 app/router.js
文件用于统一所有路由规则。
现在很多单页面,都是存在相对于的路由,你写个js,同样就要写一个路由
1 | // app/controller/user.js |
3.4 数据模型 Model(Service)
简单来说,Service 就是在复杂业务场景下用于做业务逻辑封装的一个抽象层,提供这个抽象有以下几个好处:
- 保持 Controller 中的逻辑更加简洁。
- 保持业务逻辑的独立性,抽象出来的 Service 可以被多个 Controller 重复调用。
- 将逻辑和展现分离,更容易编写测试用例。
1 | // app/service/user.js |
3.5 egg中视图 (view)
egg中的模板渲染,但是我认为前端后端分离的设计,更加有利于作为服务型架构设计,所以这边不描述view的构造
4 get、post请求
4.1 get 请求
4.1.1 query
在 URL 中 ?
后面的部分是一个 Query String,这一部分经常用于 GET 类型的请求中传递参数。例如 GET /search?name=egg&age=26
中 name=egg&age=26
就是用户传递过来的参数。我们可以通过 context.query
(为一个对象)拿到解析过后的这个参数体
1 | module.exports = app => { |
当 Query String 中的 key 重复时,context.query
只取 key 第一次出现时的值,后面再出现的都会被忽略。GET /posts?category=egg&category=koa
通过 context.query
拿到的值是 { category: 'egg' }
。
4.1.2 queries
有时候我们的系统会设计成让用户传递相同的 key,例如 GET /posts?category=egg&id=1&id=2&id=3
。针对此类情况,框架提供了 context.queries
对象,这个对象也解析了 Query String,但是它不会丢弃任何一个重复的数据,而是将他们都放到一个数组
中:
1 | // GET /posts?category=egg&id=1&id=2&id=3 |
context.queries
上所有的 key 如果有值,也一定会是数组
类型。
4.2 post 请求
1 | // 获取参数方法 post 请求 |
但是我们请求有时是get,有时是post,有时本来应该是post的请求,但是为了测试方便,还是做成get和post请求都支持的请求,于是一个能同时获取get和post请求参数的中间件就很有必要了.
4.3 编写中间层解决get、post请求
4.3.1 在app目录下新建middleware文件夹
4.3.2 在middleware里面新建params.js,内容如下
1 | /** |
本质上就是把get请求的参数和post请求的参数都放到params这个对象里,所以,不管是get还是post都能获取到请求参数
4.3.3 在/config/config.default.js里注入中间件
1 | 'use strict'; |
4.3.4 使用文章获取
1 | /** |
4.3.5 允许post请求跨域
1 | // config/plugin.js |
*一般性最好使用白名单,不要使用全部允许跨域,不安全
5 mysql数据库
框架提供了 egg-mysql 插件来访问 MySQL 数据库。这个插件既可以访问普通的 MySQL 数据库,也可以访问基于 MySQL 协议的在线数据库服务。
5.1 安装与配置
安装对应的插件 egg-mysql :
1 | npm i --save egg-mysql |
开启插件:
1 | // config/plugin.js |
在 config/config.${env}.js
配置各个环境的数据库连接信息。
5.1.1 单数据源
如果我们的应用只需要访问一个 MySQL 数据库实例,可以如下配置:
使用方式:
1 | // config/config.${env}.js |
5.1.2 多数据源
如果我们的应用需要访问多个 MySQL 数据源,可以按照如下配置:
1 | exports.mysql = { |
5.2 封装增删改查
5.2.1、插入,向users表内插入一条数据
1 | const result = await this.app.mysql.insert('users', { |
5.2.2、查询,查询users表name=Jack的数据
1 | const result = await this.app.mysql.select('users', { |
5.2.3、修改,修改users表id=1的数据age为20
1 | const result = await this.app.mysql.update('users', { |
5.2.4、删除,删除users表name=wjw的数据
1 | const result = await this.app.mysql.delete('users', { |
6 Cookie 的使用
6.1 Cookie 简介
- cookie 是存储于访问者的计算机中的变量。可以让我们用同一个浏览器访问同一个域名的时候共享数据。
- HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何关系的。
6.2 Cookie 的设置和获取
6.2.1 Cookie 设置语法
ctx.cookies.set(key, value, options)
1 | this.ctx.cookies.set('name','zhangsan'); |
6.2.2 Cookie 获取语法
ctx.cookies.get(key, options)
1 | this.ctx.cookies.get('name') |
6.2.3 清除 Cookie
1 | this.ctx.cookies.set('name',null); |
或者设置 maxAge 过期时间为 0
6.3 Cookie 参数 options
1 | ctx.cookies.set(key, value, { |
6.4 设置中文 Cookie
6.4.1 第一种解决方案
1 | console.log(new Buffer('hello, world!').toString('base64')); |
6.4.2 第二种解决方案
1 | ctx.cookies.set(key, value, { |
7 Session的使用
7.1 Session 简单介绍
session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而session 保存在服务器上。
7.2 Session 的工作流程
当浏览器访问服务器并发送第一次请求时,服务器端会创建一个 session 对象,生成一个类似于 key,value 的键值对, 然后将 key(cookie)返回到浏览器(客户)端,浏览器下次再访问时,携带 key(cookie),找到对应的 session(value)。
7.3 Egg.js 中 session 的使用
egg.js 中 session 基于 egg-session 内置了对 session 的操作
7.3.1 设置
1 | this.ctx.session.userinfo={ |
7.3.2 获取
1 | var userinfo=this.ctx.session |
7.3.3 Session 的默认设置
1 | exports.session = { |
7.4 Session 在 config.default.js 中的配置
1 | config.session={ |
7.5 cookie 和session 区别
- cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
- cookie 相比 session 没有 session 安全,别人可以分析存放在本地的 COOKIE 并进行 COOKIE欺骗。
- session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用 COOKIE。
- 单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
8 定时任务&定点任务
egg提供了强大的定时任务系统。通过定时任务,可以系统修改服务的缓存数据,以便处理需要定时更新的数据。
在app/schedule目录下新建一个js文件,每一个js文件就是一个定时任务
### 8.1 定时任务
1 | // app/schedule |
8.2 定点任务
定点任务(以每周一的5点30分0秒更新排行榜为例)
1、使用cron参数设定时间,cron参数分为6个部分,*表示所有都满足
1 | * * * * * * |
8.3 只执行一次定时任务
设置immediate参数为true时,该定时任务会在项目启动时,立即执行一次定时任务
1 | module.exports = { |
8.4 关闭任务
配置disable参数为true时,该定时任务即关闭
8.5 指定定时任务执行环境env
1 | env: ["dev", "debug"] //该定时任务在开发环境和debug模式下才执行 |
9 部署
9.1 部署服务器
首先当然是在你的服务器上部署好node服务,然后安装好。
服务器需要预装 Node.js,框架支持的 Node 版本为 >= 8.0.0。
框架内置了 egg-cluster 来启动 Master 进程,Master 有足够的稳定性,不再需要使用 pm2 等进程守护模块。
同时,框架也提供了 egg-scripts 来支持线上环境的运行和停止。
1 | egg-scripts start --port=7001 --daemon --title=egg-server-showcase |
--port=7001
端口号,默认会读取环境变量process.env.PORT
,如未传递将使用框架内置端口7001
。--daemon
是否允许在后台模式,无需nohup
。若使用 Docker 建议直接前台运行。--env=prod
框架运行环境,默认会读取环境变量process.env.EGG_SERVER_ENV
, 如未传递将使用框架内置环境prod
。--workers=2
框架 worker 线程数,默认会创建和 CPU 核数相当的 app worker 数,可以充分的利用 CPU 资源。--title=egg-server-showcase
用于方便 ps 进程时 grep 用,默认为egg-server-${appname}
。--framework=yadan
如果应用使用了可以配置package.json
的egg.framework
或指定该参数。--ignore-stderr
忽略启动期的报错。
9.1.1 启动配置项
你也可以在 config.{env}.js
中配置指定启动配置。
1 | // config/config.default.js |
path
,port
,hostname
均为 server.listen 的参数,egg-scripts
和 egg.startCluster
方法传入的 port 优先级高于此配置。
s
9.1.2 停止命令
该命令将杀死 master 进程,并通知 worker 和 agent 优雅退出。
支持以下参数:
--title=egg-server
用于杀死指定的 egg 应用,未传递则会终止所有的 Egg 应用。
1 | "start": "egg-scripts start --daemon --title=${进程名称}", |
- 你也可以直接通过
1 | ps -eo "pid,command" | grep -- "--title=egg-server" |
来找到 master 进程,并 kill
掉,无需 kill -9
。